/**
 @author 迷途小羔羊
 2015.3.5
 */
module GYLite
{
										
			
	export class GYGridH extends GYGridBase
	{
		protected _hScroller:GYScrollBarH;
		/**横向滚动Grid组件
		 * @param cols 列数 
		 * @param rows 行数 
		 * @param getGridFunc():IItemRender 返回自定义格子对象的方法 
		 * @param setGridFunc(IItemRender, any) 设置格子数据的方法*/
		public constructor(sizeW:number,sizeH:number,getGridFunc:Function=null, getThisObject:any=null, setGridFunc:Function=null, setThisObject:any=null)
		{
			super(sizeW,sizeH,getGridFunc,getThisObject,setGridFunc,setThisObject);				
		}
		protected initComponent():void
		{var s = this;
			super.initComponent();
			s._hScroller=new GYScrollBarH;
			s._hScroller.maximum = 0;
			s._hScroller.value = 0;
			s._hScroller.bottom = 0;
			s._hScroller.addEventListener(GYScrollerEvent.SCROLL_CHANGE, s.scrollChange,s);
			s._hScroller.addEventListener(GYScrollerEvent.SCROLL_TWEEN_END,s.scrollEnd,s);
			if(s._rows != 0 && s._cols != 0)
			{				
				var grid:IItemRender;
				grid=s.getGrid();				
				s._boxH = grid.height;
				s._boxW = grid.width;
				grid.dispose();
				if(s._rows > 0)
				{
					s.width = s._cols;
					s.height = s._rows;
				}
				else
				{
					s.rows = -s._rows;
					s.cols = -s._cols;
				}
			}			
		}
		/**inheritDoc*/
		public scrollToIndex(val:number):void
		{var s = this;
			s._hScroller.position = ((val / s._rows) * s._boxW >> 0);
		}
		/**inheritDoc*/
		public scrollToEndIndex(val:number):void
		{var s = this;
			s._hScroller.position = ((val / s._rows) * s._boxW - s._innerWidth + s._boxW >> 0);
		}
		protected selectLine(data:any,selectedData:any,ctrlKey:boolean,checkNext:boolean=false):void
		{var s = this;
			var ind:number=0,stInd:number=0,endInd:number=0;
			var tempData:any;
			var i:number=0,len:number=0;
			var tempVec:any[];
			var tempItem:IItemRender;
			var end:number=0,tempInd:number=0;
			var leftInd:number=0,rightInd:number=0;
			var flag:number=0,mX:number = s.mouseX,mY:number = s.mouseY;
			var selectRow:number=0,selectMax:number=0;
			if(checkNext)
			{
				if(mX > s.width)
					flag = 1;
				else if(mX < 0)
					flag = -1;
				selectRow = mY / s._boxH;
				if(flag == 0)
					return;
			}
			stInd = s._dataProvider.indexOf(selectedData);
			endInd = s._dataProvider.indexOf(data);
			if(flag != 0)
			{
				if(flag == 1)
				{
					endInd += s._rows;
					endInd = endInd - endInd % s._rows + selectRow;
					selectMax = s._dataProvider.length - s._dataProvider.length % s._rows + selectRow;
					if(selectMax >= s._dataProvider.length)
						selectMax = s._dataProvider.length - 1;
					endInd = endInd < selectMax? endInd: selectMax;
					data = s._dataProvider[endInd];
				}
				else if(flag == -1)
				{
					endInd -= s._rows;
					endInd = endInd - endInd % s._rows + selectRow;
					endInd = endInd > 0? endInd:0;
					data = s._dataProvider[endInd];
				}
				s.scrollToEndIndex(endInd);
			}
			s._nextData = data;
			if(endInd < stInd)
			{
				ind = endInd;
				endInd = stInd;
				stInd = ind;
			}
			len = endInd + 1;
			end = s._selectList.length-1;
			if(s._selectMode == 0)
			{
				leftInd = stInd % s._rows;
				rightInd = endInd % s._rows;
				if(rightInd < leftInd)
				{
					ind = rightInd;
					rightInd = leftInd;
					leftInd = ind;
				}
				for(i=stInd;i<len;++i)
				{
					tempInd = i % s._rows;
					if(tempInd < leftInd || tempInd > rightInd)
						continue;
					tempData = s._dataProvider[i];
					ind = end > -1? s._selectList.lastIndexOf(tempData,end) : -1;
					if(ind == -1)
					{
						if(s._selectList.length >= s._canSelectNum)
							continue;
						if(tempData)
						{
							tempItem = s._dataToItemDict.getValue(tempData);
							s._selectList.push(tempData);
							if(tempItem)
								tempItem.selected = true;
						}
					}
					else if(!ctrlKey)
					{
						tempData = s._selectList[end];
						s._selectList[end] = s._selectList[ind];
						s._selectList[ind]= tempData;
						--end;
					}
				}
			}
			else
			{
				for(i=stInd;i<len;++i)
				{
					if(s._selectList.length >= s._canSelectNum)
						break;
					tempData = s._dataProvider[i];
					ind = end > -1? s._selectList.lastIndexOf(tempData,end) : -1;
					if(ind == -1)
					{
						if(tempData)
						{
							tempItem = s._dataToItemDict.getValue(tempData);
							s._selectList.push(tempData);
							if(tempItem)
								tempItem.selected = true;
						}
					}
					else if(!ctrlKey)
					{
						tempData = s._selectList[end];
						s._selectList[end] = s._selectList[ind];
						s._selectList[ind]= tempData;
						--end;
					}
				}
			}
			if(!ctrlKey && end > -1)
			{
				tempVec = s._selectList.splice(0,end + 1);
				len = tempVec.length;
				while(--len>-1)
				{
					tempItem = s._dataToItemDict.getValue(tempVec[len]);
					if(tempItem)
					{
						tempItem.selected = false;
					}
				}
			}
			if(s.hasEventListener(GYViewEvent.SELECTED) && s._mouseSelect)
			{
				s.dispatchEvent(new GYViewEvent(GYViewEvent.SELECTED));
				s._mouseSelect = false;
			}
		}
		/**横向滚动条*/
		public get hScroller():GYScrollBarH
		{var s = this;
			return s._hScroller;
		}
		/**@inheritDoc*/
		public updateGrid():void
		{var s = this;
			var w:number;
			var i:number,j:number,nowRow:number;
			var grid:IItemRender;
			for(i=0;i<s._cols;++i)
			{
				nowRow = i * s._rows;
				for(j=0;j<s._rows;++j)
				{
					grid=s._grids[nowRow + j];
					grid.width = s._boxW;
					grid.height = s._boxH;
				}
			}
			w = s._boxW + s._paddingR;
			s._max=s._dataProvider == null?s.baseWidth:Math.max(Math.ceil(s._dataProvider.length/s._rows) * w - s._paddingR, s.baseWidth);
			s._hScroller.maximum = s._max-s.baseWidth + s._scrollPadLeft + s._scrollPadRight;
			s._hScroller.barPercent = s.baseWidth/s._max;
			if(s._hScroller.value > s._hScroller.maximum)
				s._hScroller.value = s._hScroller.maximum;
			s.scrollerPolicy = s._scrollerPolicy;
			s.scrollChange(null, true);
		}
		public set dataProvider(val:Array<any>)
		{var s = this;
			if(!s._keepSelected)
			{
				s._selectedData = null;
				s._selectIndex = -1;
				if(s._canSelectNum > 1)
					s._selectList.length = 0;
			}
			var w:number=s._boxW + s._paddingR;
			s._dataProvider=(val?val:[]);
			if(!s._virtual_layout)
			{
				s.cols = s._dataProvider.length;
				if(!s._boxNumUpdate)
					s.boxNumChange(true);
			}
			if(s._boxNumUpdate)
				s._boxNumUpdateReset = true;
			s._max=Math.max((s._rows==0?0:Math.ceil(s._dataProvider.length/s._rows)) * w - s._paddingR, s.baseWidth);
			s._hScroller.maximum = s._max-s.baseWidth + s._scrollPadLeft + s._scrollPadRight;
			s._hScroller.barPercent = s.baseWidth/s._max;
			if(s._hScroller.position > s._hScroller.maximum)
				s._hScroller.position = s._hScroller.maximum;
			s.scrollerPolicy = s._scrollerPolicy;
			s.scrollChange(null, true);
		}
		public get dataProvider():Array<any>
		{var s = this;
			return s._dataProvider;
		}
		private scrollChange(e:GYScrollerEvent=null, update:boolean = false, updatePos:boolean = true)
		{var s = this;
			var val:number;
			if(s._dataProvider==null)
				return;
			if(s._boxNumUpdate)return;
			var w:number;
			var h:number;
			var line:number;
			var offset:number;
			var i:number,j:number;
			var grid:IItemRender;
			var nowLine:number;
			val = s._hScroller.position;
			if(!s._virtual_layout)
			{
				s.clipX = val;
				return;
			}
			w=s._boxW + s._paddingR;
			h=s._boxH + s._paddingB;
			offset=val % w;
			nowLine=(val / w >> 0);			
			line = 0;
			if(!update)
			{
				line=s._lastLine-nowLine;
				if(line < 0)
				{
					if(-line<s._cols)
					{
						for(i=0;i<-line;++i)
						{
							for(j=0;j<s._rows;++j)
							{
								grid=s._grids.shift();
								s._grids.push(grid);
							}
						}
					}
				}
				else if(line > 0)
				{
					if(line<s._cols)
					{
						for(i=0;i<line;++i)
						{
							for(j=0;j<s._rows;++j)
							{
								grid=s._grids.pop();
								s._grids.unshift(grid);
							}
						}
					}
				}
			}
			var tempLine:number= s._cols + line - 1;
			var isSet:boolean;
			var ind:number;
			for(i=0;i<s._cols;++i)
			{
				isSet = (line > 0 && i < line || line < 0 && i > tempLine || update);
				for(j=0;j<s._rows;++j)
				{
					grid = s._grids[i*s._rows + j];
					ind = (nowLine+i)*s._rows+j;
					grid.itemIndex = ind;
					var obj:any=s._dataProvider[ind];
					if(isSet)
						s.setGrid(grid,obj);
					if(updatePos)
					{
						grid.x = w * i - offset;
						grid.y = h * j;
					}					
				}
			}
			s._lastLine = nowLine;
		}
		/**刷新列表可见的所有项*/		
		public updateItems():void
		{var s = this;
			s.scrollChange(null,true, false);
		}
		public set height(val:number)
		{var s = this;
			if(s.$height == val)
				return;
			s._innerHeight = val;
			s.group_height = s._innerHeight + (s._hScroller.parent?s._hScroller.height:0);
			s.rows = (s._boxH + s._paddingB > 0)?(s._innerHeight / (s._boxH + s._paddingB) >> 0):0;
		}
		public get height():number
		{var s = this;
			return egret.superGetter(GYGridH, this, "height");
		}
		public set width(val:number)
		{var s = this;			
			if(s.$width == val)
				return;
			s._innerWidth = s._hScroller.width = s.group_width = val;
			var w:number = s.baseWidth;
			s._max=s._dataProvider == null?w:Math.max(Math.ceil(s._dataProvider.length/s._rows) * (s._boxW + s._paddingR) - s._paddingR, w);
			s._hScroller.maximum = s._max-w + s._scrollPadLeft + s._scrollPadRight;
			s._hScroller.barPercent = w/s._max;
			s.scrollerPolicy = s._scrollerPolicy;
			s.cols = (s._boxW + s._paddingR > 0)?Math.ceil(s._innerWidth / (s._boxW + s._paddingR)) + 1:1;
		}
		public get width():number
		{var s = this;			
			return egret.superGetter(GYGridH, this, "width");
		}
		public set rows(val:number)
		{var s = this;
			if(val < 0)return;
			if(val == s._rows)return;
			s._rows = val;
			s.invalidBoxNum();
		}
		public get rows():number
		{
			return this._rows;
		}
		public set cols(val:number)
		{var s = this;
			if(val < 0)return;
			if(val == s._cols)return;			
			s._cols = s._virtual_layout?val:Math.ceil((s._dataProvider && s._rows > 0)?s._dataProvider.length / s._rows:0);
			s.invalidBoxNum();
		}
		public get cols():number
		{
			return this._cols;
		}
		protected boxNumChange(update:boolean=false):void
		{
			var i:number,j:number;
			var grid:IItemRender;
			var ind:number;
			var isNew:Boolean;
			var w:number;
			var h:number;
			var len:number;
			var offset:number;
			var s = this;
			w = s._boxW + s._paddingR;
			h = s._boxH + s._paddingB;			
			offset = s._virtual_layout?s._hScroller.position % w:0;
			len = s._grids.length;
			for(j=0;j<s._cols;++j)
			{
				for(i=0;i<s._rows;++i)
				{
					ind = j * s._rows + i;
					isNew = s._grids[ind] == null;
					if(isNew)
					{
						s._grids[ind] = grid = s.getGrid();
					}
					else
						grid = s._grids[ind];
					if(s._dataProvider && (isNew || update))
					{
						grid.itemIndex = ind;
						s.setGrid(grid,s._dataProvider[s._lastLine*s._rows + ind]);
						grid.selected = s._selectedData!=null && grid.getData() == s._selectedData;
					}
					grid.x = w * j - offset;
					grid.y = h * i;
					s.addElementAt(grid,0);
				}
			}
			i = s._cols * s._rows;
			for(;i<len;++i)
			{
				grid = s._grids[i];
				if(grid.parent)
					(<any>grid.parent).removeElement(grid);
			}
			s._grids.length = s._cols * s._rows;
		}
		protected wheelRoll(e)
		{var s = this;			
			if(!s._wheelScroll)return;
			if(s._isDragging && s.dragForbiddenWheel)return;
			var val:number;
			val = s._wheelStep == 0?s._boxW:s._wheelStep;
			if(e.deltaY > 0)
				s._hScroller.position += val;
			else
				s._hScroller.position -= val;
		}		
		public set scrollerPolicy(val:number)
		{var s = this;
			s._scrollerPolicy=val;
			var show:boolean;
			if(s._scrollerPolicy == 0)
			{
				if(s._hScroller.barPercent < 1)
					show = true;
				else
					show = false;
			}
			else if(s._scrollerPolicy == 1)
				show = true;
			else
				show = false;
			if(show)
			{
				if(s._hScroller.parent == null)
				{
					s.baseAdd(s._hScroller);					
					s.group_height = s._innerHeight + (s._hScroller.parent?s._hScroller.height:0);
				}
			}
			else
			{
				if(s._hScroller.parent)
				{
					s.baseRemove(s._hScroller);
					s.group_height = s._innerHeight;
				}
			}
		}		
		/**滚动条 0自动 1显示 2不显示*/
		public get scrollerPolicy():number
		{var s = this;
			return s._scrollerPolicy;
		}
		protected downGroup(e:egret.TouchEvent)
		{var s = this;			
			if(s.mouseY >= s._hScroller.y && s.mouseY <= s._hScroller.y + s._hScroller.height)
				return;
			s._touchId = e.touchPointID;
			if(GYSprite.pushGlobalDrag(this))
				s.groupDrag();
			else
				s.addEventListener(GYEvent.GLOABL_DRAG, s.globalDragCall,s);
		}
		protected dragLoop(t:number):void
		{var s = this;
			var mX:number;
			let nt:number;
			let frameParam:number;
			let xFlag:boolean;
			let temp:number;
			nt = Date.now();
			frameParam = 1000/egret.ticker.$frameRate|0;			
			xFlag = s._moveXTime < 100;			
			s._moveXTime = xFlag?s._moveXTime + Math.min(frameParam,nt - s._lastXDragTime):Math.min(frameParam,nt - s._lastXDragTime);
			mX = s.mouseX - s._clipRect.x;
			s._lastYDragTime = s._lastXDragTime = nt;
			temp = s.tempX - mX;
			if(s._dragLock || Math.abs(temp) > s.dragValue)
			{
				s._isDragging = true;
				s.dragLock = true;
				s.easeSpeedX = xFlag?s.easeSpeedX+temp:temp;
				if(s.easeSpeedX == 0)				
					return;				
				s._hScroller.position += temp;
				s.tempX = mX;
				if(s._hScroller.position == 0 && s.easeSpeedX < 0 || s._hScroller.position == s._hScroller.maximum && s.easeSpeedX > 0)
				{
					if(GYSprite.shiftGlobalDrag(2))
						s.clearGlobalDrag();
				}
			}
			else if(GYLite.GYSprite.hasGlobalVDrag())
			{
				let dragMoveY:boolean;
				var mY:number = s.mouseY - s._clipRect.y;
				dragMoveY = Math.abs(s.tempY - mY) > s.dragValue;
				s.tempY = mY;
                if(dragMoveY)
					++GYLite.GYSprite.globalVDrag;
                if(GYLite.GYSprite.globalVDrag > GYLite.GYSprite.globalVDragCount)
                {
                    if (GYLite.GYSprite.shiftGlobalDrag(2))
                        s.clearGlobalDrag();
                }
			}
		}
		protected groupDrag():void
		{var s = this;
			if(s._hScroller.tween)
				s.dragLock = true;
			s._hScroller.stopScroll();
			// CommonUtil.addStageLoop(s.dragLoop,s);
			GYSprite.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE,s.touchMove,s);
			s._lastYDragTime = s._lastXDragTime = Date.now();
			s.tempX = s.mouseX - s._clipRect.x;			
			s._moveXTime = s.easeSpeedX = 0;
			s._scrollToPos = NaN;
			GYSprite.addStageDown(s,s.upGroup,s);
			s.addEventListener(egret.TouchEvent.TOUCH_END, s.upGroup, s);
		}		
		protected groupDragStop():void
		{var s = this;
			if(s.tempX != s.tempX)return;
			s._isDragging = false;
			let dis:number,minDis:number;
			let temp:number,tarPos:number,addDis:number;
			let frameParam:number;			
			frameParam = 1000/egret.ticker.$frameRate;
			s.removeEventListener(egret.TouchEvent.TOUCH_END, s.upGroup, s);
			// CommonUtil.delStageLoop(s.dragLoop,s);
			GYSprite.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE,s.touchMove,s);
			let nt:number = Date.now();
			let dt:number = s._moveXTime;			
			let spd:number;
			if(dt > 0 && nt - s._lastXDragTime < s._easeTriggerTime && (s.easeSpeedX > s.easeValue || s.easeSpeedX < -s.easeValue))
			{
				spd = s.easeSpeedX / dt * frameParam * s.speedParam;	
				dis = (s._hScroller.limitMax == s._hScroller.limitMax && s._hScroller.limitMax < s._hScroller.maximum)?s._hScroller.limitMax:s._hScroller.maximum;
				minDis = (s._hScroller.limitMin == s._hScroller.limitMin && s._hScroller.limitMin > 0)?s._hScroller.limitMin:0;
				addDis = Math.abs(spd) * spd * s._easeSpeedValue;
				temp = s._hScroller.position + addDis;
				if(temp < minDis)
				{
					tarPos = minDis;
					addDis = tarPos - s._hScroller.position;
				}						
				else if(temp > dis)
				{
					tarPos = dis;
					addDis = tarPos - s._hScroller.position;
				}
				else
				{
					tarPos = temp;					
				}				
				s._hScroller.scrollToPosition(tarPos, (temp < minDis || temp > dis)?s._easeTime: Math.abs(addDis / spd * frameParam * 2));
			}
			else if(s._scrollPosLimit == s._scrollPosLimit)
			{
				s.scrollEnd();
			}
			s.tempX = NaN;
			s.dragLock = false;
		}

		public scrollToNextItem():number
		{let s =this;			
			let pos:number;
			let pad:number;
			let nextPos:number;
			if(!s._overlying)
			{							
				if(s._hScroller.tween)return;
			}
			nextPos = s._scrollToPos == s._scrollToPos?s._scrollToPos:s._hScroller.position;
			if(nextPos > s.hScroller.maximum)return;
			pad = s._scrollPosLimit == s._scrollPosLimit?s._scrollPosLimit:(s._boxW + s._paddingR);
			pos = ((nextPos / pad >> 0) + 1) * pad;
			pos = pos > s.hScroller.limitMax?s.hScroller.limitMax:(pos > s.hScroller.maximum?s.hScroller.maximum:pos);
			s.hScroller.scrollToPosition(pos, s.scrollNextTime == s.scrollNextTime?s.scrollNextTime:pad);
			s._scrollToPos = pos;
			return pos;
		}		
		public scrollToPreItem():number
		{let s =this;
			let pos:number;
			let pad:number;
			let nextPos:number;
			if(s._overlying)
			{
				nextPos = s._scrollToPos == s._scrollToPos?s._scrollToPos:s._hScroller.position;
				if(nextPos < 0)return;			
			}
			else
			{
				if(s._hScroller.tween)return;
			}
			pad = s._scrollPosLimit == s._scrollPosLimit?s._scrollPosLimit:(s._boxW + s._paddingR);
			if(nextPos % pad == 0)
				pos = ((nextPos / pad >> 0) - 1) * pad;
			else	
				pos = ((nextPos / pad >> 0) * pad);
			pos = pos < s.hScroller.limitMin?s.hScroller.limitMin:(pos < 0?0:pos);
			s.hScroller.scrollToPosition(pos, s.scrollNextTime == s.scrollNextTime?s.scrollNextTime:pad);
			s._scrollToPos = pos;
			return pos;
		}
		protected scrollEnd(e:GYScrollerEvent=null):void
		{let s =this;
			if(s._scrollPosLimit != s._scrollPosLimit)return;
			if(s._scrollToPos != s._scrollToPos || s._scrollToPos == s._scrollToPos && Math.abs(s._scrollToPos - s._hScroller.position) > 1)
			{
				s._scrollToPos = NaN;
				if(s.easeSpeedX > 0)
					s.scrollToNextItem();
				else if(s.easeSpeedX < 0)
					s.scrollToPreItem();
				else
				{
					let offset:number;
					offset = s.hScroller.position % s.scrollPosLimit;
					if(offset > 0)
					{
						if(offset > s.scrollPosLimit / 2)
						{
							s.scrollToNextItem();
						}
						else
						{
							s.scrollToPreItem();
						}
					}				
				}
				s.easeSpeedX = 0;
			}
			else
				s._scrollToPos = NaN;
		}
	}
}